import {
  CanActivate,
  ExecutionContext,
  ForbiddenException,
  Injectable,
} from '@nestjs/common';
import { Observable } from 'rxjs';
import { UserService } from '../user/user.service';
import { Reflector } from '@nestjs/core';
import { PermissionService } from './permission.service';

@Injectable()
export class PermissionGuard implements CanActivate {
  constructor(
    private readonly reflector: Reflector,
    private readonly userService: UserService, // 用来获取用户权限的服务
    private readonly permissionService: PermissionService, // 用来获取用户的权限列表的服务
  ) {}

  async canActivate(context: ExecutionContext) {
    // 获取当前请求的用户对象
    const request = context.switchToHttp().getRequest();
    const user = request.user; // 假设用户信息存储在请求中

    // 获取路由上需要的权限
    const requiredPermissions = this.reflector.get<string[]>(
      'permissions',
      context.getHandler(),
    );
    console.log('permission.guard.ts-canActivate-');

    if (!requiredPermissions) {
      // 如果没有指定权限，默认通过
      return true;
    }

    // 获取用户的权限列表（假设权限存储在用户对象中）
    const userPermissions = await this.permissionService.findAllPermissions();
    const hasPermission = await this.checkPermissions(
      userPermissions,
      requiredPermissions,
    );

    if (!hasPermission) {
      // 如果用户没有足够的权限，抛出 ForbiddenException
      throw new ForbiddenException(
        'You do not have permission to access this resource',
      );
    }

    return true;
  }

  // 检查用户是否具有所需的权限，包括父权限的检查
  private async checkPermissions(
    userPermissions: any[],
    requiredPermissions: string[],
  ): Promise<boolean> {
    // 递归校验用户权限和父权限
    const checkPermission = async (permissionKey: string): Promise<boolean> => {
      const permission = userPermissions.find(
        (perm) => perm.permission_key === permissionKey,
      );

      if (permission) {
        return true;
      }

      // 如果没有找到该权限，检查父权限
      if (permission?.parentId) {
        const parentPermission = await this.permissionService.findOne(
          permission.parentId,
        );
        return checkPermission(parentPermission.permission_key); // 递归检查父权限
      }

      return false;
    };

    // 检查每个必需权限
    for (const permission of requiredPermissions) {
      const isValid = await checkPermission(permission);
      if (!isValid) {
        return false; // 如果有一个权限不满足，返回 false
      }
    }

    return true; // 如果所有权限都满足，返回 true
  }
}
